using System;
using System.Collections.Generic;
using System.IO;

namespace Fadd.Logging
{
    /// <summary>
    /// Writes log entries to a text file.
    /// </summary>
    public class TextFileLogger : Logger
    {
        private readonly TextFileConfiguration _configuration;

		/// <summary>
		/// Log entries that are waiting on being written
		/// </summary>
    	private readonly Queue<string> _messages = new Queue<string>();

		/// <summary>
		/// We are currently writing log entries to disk
		/// </summary>
    	private bool _isWriting;

		
        /// <summary>
        /// Initializes a new instance of the <see cref="ConsoleLogger"/> class.
        /// </summary>
        /// <param name="logFormatter">The log formatter.</param>
        /// <param name="configuration">Configuration for the logger.</param>
        /// <exception cref="ArgumentException">Configuration is not of type <see cref="TextFileConfiguration"/>.</exception>
		public TextFileLogger(LogFormatter logFormatter, ILoggerConfiguration configuration)
            : base(logFormatter, configuration)
        {
			if (!(configuration is TextFileConfiguration))
				throw new ArgumentException("Configuration is not of type TextFileConfiguration.");
			_configuration = (TextFileConfiguration)configuration;
        }


        #region ILogger Members

        /// <summary>
        /// Very detailed log messages, potentially of a high frequency and volume
        /// </summary>
        /// <param name="message">message written to the log.</param>
        public override void Trace(string message)
        {
			AddEntry(LogLevel.Trace, message);
        }

        /// <summary>
        /// Very detailed log messages, potentially of a high frequency and volume
        /// </summary>
        /// <param name="message">message written to the log.</param>
        /// <param name="exception">an exception.</param>
        public override void Trace(string message, Exception exception)
        {
			AddEntry(LogLevel.Trace, message, exception);
        }

        /// <summary>
        /// Less detailed and/or less frequent debugging messages
        /// </summary>
        /// <param name="message">message written to the log.</param>
        public override void Debug(string message)
        {
			AddEntry(LogLevel.Debug, message);
        }

        /// <summary>
        /// Less detailed and/or less frequent debugging messages
        /// </summary>
        /// <param name="message">message written to the log.</param>
        /// <param name="exception">an exception.</param>
        public override void Debug(string message, Exception exception)
        {
			AddEntry(LogLevel.Debug, message, exception);
        }

        /// <summary>
        /// Informational messages
        /// </summary>
        /// <param name="message">message written to the log.</param>
        public override void Info(string message)
        {
			AddEntry(LogLevel.Info, message);
        }

        /// <summary>
        /// Informational messages
        /// </summary>
        /// <param name="message">message written to the log.</param>
        /// <param name="exception">an exception.</param>
        public override void Info(string message, Exception exception)
        {
			AddEntry(LogLevel.Info, message, exception);
        }

        /// <summary>
        /// Warnings which don't appear to the user of the application
        /// </summary>
        /// <param name="message">message written to the log.</param>
        public override void Warning(string message)
        {
			AddEntry(LogLevel.Warning, message);
        }

        /// <summary>
        /// Warnings which don't appear to the user of the application
        /// </summary>
        /// <param name="message">message written to the log.</param>
        /// <param name="exception">an exception.</param>
        public override void Warning(string message, Exception exception)
        {
			AddEntry(LogLevel.Warning, message, exception);
        }

        /// <summary>
        /// Error messages
        /// </summary>
        /// <param name="message">message written to the log.</param>
        public override void Error(string message)
        {
			AddEntry(LogLevel.Error, message);
        }

        /// <summary>
        /// Error messages
        /// </summary>
        /// <param name="message">message written to the log.</param>
        /// <param name="exception">an exception.</param>
        public override void Error(string message, Exception exception)
        {
            AddEntry(LogLevel.Error, message, exception);
        }

        /// <summary>
        /// Fatal error messages. After a fatal error, the application usually terminates. 
        /// </summary>
        /// <param name="message">message written to the log.</param>
        public override void Fatal(string message)
        {
            AddEntry(LogLevel.Fatal, message);
        }

        /// <summary>
        /// Fatal error messages. After a fatal error, the application usually terminates. 
        /// </summary>
        /// <param name="message">message written to the log.</param>
        /// <param name="exception">an exception.</param>
        public override void Fatal(string message, Exception exception)
        {
            AddEntry(LogLevel.Fatal, message, exception);
        }

        #endregion


        private void AddEntry(LogLevel level, string message)
        {
			WriteMessage(FormatEntry(level, message, null));
        }

		private void AddEntry(LogLevel level, string message, Exception exception)
        {
			WriteMessage(FormatEntry(level, message, exception));
        }

		private void WriteMessage(string msg)
		{
			lock (this)
			{
				_messages.Enqueue(msg);

				if (_isWriting)
					return;

				_isWriting = true;
			}

			string entry;
			while (_messages.Count > 0)
			{
				lock (this)
				{
					if (_messages.Count == 0)
						return;
					entry = _messages.Dequeue();
				}


				//File.AppendText()
			}
				
		}
    }
}
